#include "CudaEpiModel.h"
#include <pthread.h>
using namespace std;

#ifndef CUDA_PARAM_H
#define CUDA_PARAM_H

#define NUM_GPUS 4

extern EpiModel* model;


struct GPUSimStruct{
	int gpu_id;

	dRandVec* rand_vec;

	// 3 component is concurrency for transfer from cpu tp gpu, computing infection and transfer gpu to cpu
	// each iteration component status will be different
	dPersonVec* ppl_vec[3];
	dPersonVec* comm_worker_vec[3];

	// 2 host vector one is for uploading from cpu t0 gpu and the other is from gpu to cpu
	vector<Person>* host_ppl_vec[2];
	vector<Person>* host_comm_worker_vec[2];

	// community data
	dCommunityVec* comm_vec;
	hCommunityVec* host_comm_vec;

	dTractVec* tract_vec;

	// each entry indict the start and end of worker index of a community
	thrust::device_vector<int>* comm_worker_start_vec;
	thrust::device_vector<int>* comm_worker_end_vec;

	// use to partition infectious and infected people
	thrust::device_vector<int>* home_ppl_index;
	thrust::device_vector<int>* worker_ppl_index;

	// use to assign infection
	thrust::device_vector<bool>* home_infect_result;
	thrust::device_vector<bool>* worker_infect_result;

	// for each entry means in this iteration the first community and last community it dealing with
	vector<int>* iter_comm_start;
	vector<int>* iter_comm_end;

	pthread_barrier_t barr;

	cudaError err;
};

extern GPUSimStruct gpu_data[NUM_GPUS];

extern vector<int>* host_comm_worker_start_vec;
extern vector<int>* host_comm_worker_end_vec;

extern int num_gpu_iter; // number of gpu iterations of calculating the day function
extern int num_gpu_ppl; // number of ppl on a gpu at one iteration
extern int num_outside_worker; // totoal number of outside workers


// transfer epimodel person and worker vector information from cpu to gpu
// iter means iteration in the pipline
// vec_id mean which lane of the pipline it is tranfering
void uploadVec(GPUSimStruct& data, int iter, int vec_id);

// transfer epimodel person and worker information from gpu to cpu
// paramter sames as uploadVec
void downloadVec(GPUSimStruct& data, int iter, int vec_id);

void computeDay(GPUSimStruct& data, int iter, int vec_id);

#endif
